<!DOCTYPE html>
<html id="docs" lang="en" class="">
	<head>
	<meta charset="utf-8">
<title>Custom Resources - Kubernetes</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" type="image/png" href="../../../../images/favicon.png">
<link rel="stylesheet" type="text/css" href="../../../../css/base_fonts.css">
<link rel="stylesheet" type="text/css" href="../../../../css/styles.css">
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.css">
<link rel="stylesheet" type="text/css" href="../../../../css/callouts.css">
<link rel="stylesheet" type="text/css" href="../../../../css/custom-jekyll/tags.css">




<meta name="description" content="Custom Resources" />
<meta property="og:description" content="Custom Resources" />

<meta property="og:url" content="https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/" />
<meta property="og:title" content="Custom Resources - Kubernetes" />

<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script
src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU="
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.js"></script>
<script src="../../../../js/script.js"></script>
<script src="../../../../js/custom-jekyll/tags.js"></script>


	</head>
	<body>
		<div id="cellophane" onclick="kub.toggleMenu()"></div>

<header>
    <a href="../../../../index.html" class="logo"></a>

    <div class="nav-buttons" data-auto-burger="primary">
        <ul class="global-nav">
            
            
            <li><a href="../../../home.1">Documentation</a></li>
            
            <li><a href="../../../../blog/index.html">Blog</a></li>
            
            <li><a href="../../../../partners/index.html">Partners</a></li>
            
            <li><a href="../../../../community/index.html">Community</a></li>
            
            <li><a href="../../../../case-studies/index.html">Case Studies</a></li>
            
            
             <li>
                <a href="index.html#">
                    English <span class="ui-icon ui-icon-carat-1-s"></span>
                </a>
                <ul>
                
                    <li><a href="../../../../zh/index.html">中文 Chinese</a></li>
                
                    <li><a href="../../../../ko/index.html">한국어 Korean</a></li>
                
                </ul>
            </li>
         
            <li>
                <a href="index.html#">
                    v1.11 <span class="ui-icon ui-icon-carat-1-s"></span>
                </a>
                <ul>
                
                    <li><a href="https://kubernetes.io">v1.12</a></li>
                
                    <li><a href="../../../../index.html">v1.11</a></li>
                
                    <li><a href="https://v1-10.docs.kubernetes.io">v1.10</a></li>
                
                    <li><a href="https://v1-9.docs.kubernetes.io">v1.9</a></li>
                
                </ul>
            </li>
        </ul>
        
        <a href="../../../tutorials/kubernetes-basics/index.html" class="button" id="tryKubernetes" data-auto-burger-exclude>Try Kubernetes</a>
        <button id="hamburger" onclick="kub.toggleMenu()" data-auto-burger-exclude><div></div></button>
    </div>

    <nav id="mainNav">
        <main data-auto-burger="primary">
        <div class="nav-box">
            <h3><a href="../../../tutorials/stateless-application/hello-minikube/index.html">Get Started</a></h3>
            <p>Ready to get your hands dirty? Build a simple Kubernetes cluster that runs "Hello World" for Node.js.</p>
        </div>
        <div class="nav-box">
            <h3><a href="../../../home.1">Documentation</a></h3>
            <p>Learn how to use Kubernetes with the use of walkthroughs, samples, and reference documentation. You can even <a href="../../../../editdocs/index.html" data-auto-burger-exclude>help contribute to the docs</a>!</p>
        </div>
        <div class="nav-box">
            <h3><a href="../../../../community/index.html">Community</a></h3>
            <p>If you need help, you can connect with other Kubernetes users and the Kubernetes authors, attend community events, and watch video presentations from around the web.</p>
        </div>
        <div class="nav-box">
            <h3><a href="../../../../blog/index.html">Blog</a></h3>
            <p>Read the latest news for Kubernetes and the containers space in general, and get technical how-tos hot off the presses.</p>
        </div>
        </main>
        <main data-auto-burger="primary">
        <div class="left">
            <h5 class="github-invite">Interested in hacking on the core Kubernetes code base?</h5>
            <a href="https://github.com/kubernetes/kubernetes" class="button" data-auto-burger-exclude>View On Github</a>
        </div>

        <div class="right">
            <h5 class="github-invite">Explore the community</h5>
            <div class="social">
                <a href="https://twitter.com/kubernetesio" class="twitter"><span>Twitter</span></a>
                <a href="https://github.com/kubernetes/kubernetes" class="github"><span>Github</span></a>
                <a href="http://slack.k8s.io/" class="slack"><span>Slack</span></a>
                <a href="http://stackoverflow.com/questions/tagged/kubernetes" class="stack-overflow"><span>Stack Overflow</span></a>
                <a href="https://discuss.kubernetes.io" class="mailing-list"><span>Forum</span></a>
                <a href="https://calendar.google.com/calendar/embed?src=nt2tcnbtbied3l6gi2h29slvc0%40group.calendar.google.com" class="calendar"><span>Events Calendar</span></a>
            </div>
        </div>
        <div class="clear" style="clear: both"></div>
        </main>
    </nav>
</header>

		
		
		<section id="hero" class="light-text no-sub">
			









<h1>Concepts</h1>
<h5></h5>








<div id="vendorStrip" class="light-text">
	<ul>
		
		
		<li><a href="../../../home.1">DOCUMENTATION</a></li>
		
		
		<li><a href="../../../setup/index.html">SETUP</a></li>
		
		
		<li><a href="../../index.html" class="YAH">CONCEPTS</a></li>
		
		
		<li><a href="../../../tasks/index.html">TASKS</a></li>
		
		
		<li><a href="../../../tutorials/index.html">TUTORIALS</a></li>
		
		
		<li><a href="../../../reference.1">REFERENCE</a></li>
		
	</ul>
	<div id="searchBox">
		<input type="text" id="search" placeholder="Search" onkeydown="if (event.keyCode==13) window.location.replace('/docs/search/?q=' + this.value)" autofocus="autofocus">
	</div>
</div>

		</section>
		
		
<section id="deprecationWarning">
  <main>
    <div class="content deprecation-warning">
      <h3>
        Documentation for Kubernetes v1.11 is no longer actively maintained. The version you are currently viewing is a static snapshot.
        For up-to-date documentation, see the <a href="https://kubernetes.io/docs/home/">latest</a> version.
      </h3>
    </div>
  </main>
</section>


		<section id="encyclopedia">
			
<div id="docsToc">
     <div class="pi-accordion">
    	
        
        
        
        
        
         
             
                 
             
         
             
                 
             
         
             
                 
                          
                          
                 
             
         
             
         
             
         
             
         
             
         
             
         
         
        
        <a class="item" data-title="Concepts" href="../../index.html"></a>

	
	
		
		
	<div class="item" data-title="Overview">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="What is Kubernetes?" href="../../overview/index.html"></a>

		
	
		
		
<a class="item" data-title="Kubernetes Components" href="../../overview/components.1"></a>

		
	
		
		
<a class="item" data-title="The Kubernetes API" href="../../overview/kubernetes-api/index.html"></a>

		
	
		
		
	<div class="item" data-title="Working with Kubernetes Objects">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Understanding Kubernetes Objects" href="../../overview/working-with-objects/kubernetes-objects.1"></a>

		
	
		
		
<a class="item" data-title="Names" href="../../../user-guide/identifiers"></a>

		
	
		
		
<a class="item" data-title="Namespaces" href="../../overview/working-with-objects/namespaces.1"></a>

		
	
		
		
<a class="item" data-title="Labels and Selectors" href="../../../user-guide/labels"></a>

		
	
		
		
<a class="item" data-title="Annotations" href="../../overview/working-with-objects/annotations.1"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Object Management Using kubectl">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Kubernetes Object Management" href="../../../tutorials/object-management-kubectl/object-management/index.html"></a>

		
	
		
		
<a class="item" data-title="Managing Kubernetes Objects Using Imperative Commands" href="../../../tutorials/object-management-kubectl/imperative-object-management-command/index.html"></a>

		
	
		
		
<a class="item" data-title="Imperative Management of Kubernetes Objects Using Configuration Files" href="../../../tutorials/object-management-kubectl/imperative-object-management-configuration/index.html"></a>

		
	
		
		
<a class="item" data-title="Declarative Management of Kubernetes Objects Using Configuration Files" href="../../../tutorials/object-management-kubectl/declarative-object-management-configuration/index.html"></a>

		
	

		</div>
	</div>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Compute, Storage, and Networking Extensions">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Cluster Administration Overview" href="../../cluster-administration/cluster-administration-overview/index.html"></a>

		
	
		
		
<a class="item" data-title="Certificates" href="../../cluster-administration/certificates/index.html"></a>

		
	
		
		
<a class="item" data-title="Cloud Providers" href="../../cluster-administration/cloud-providers/index.html"></a>

		
	
		
		
<a class="item" data-title="Managing Resources" href="../../cluster-administration/manage-deployment/index.html"></a>

		
	
		
		
<a class="item" data-title="Cluster Networking" href="../../../admin/networking"></a>

		
	
		
		
<a class="item" data-title="Logging Architecture" href="../../cluster-administration/logging.1"></a>

		
	
		
		
<a class="item" data-title="Configuring kubelet Garbage Collection" href="../../cluster-administration/kubelet-garbage-collection/index.html"></a>

		
	
		
		
<a class="item" data-title="Federation" href="../../cluster-administration/federation/index.html"></a>

		
	
		
		
<a class="item" data-title="Proxies in Kubernetes" href="../../cluster-administration/proxies/index.html"></a>

		
	
		
		
<a class="item" data-title="Controller manager metrics" href="../../cluster-administration/controller-metrics/index.html"></a>

		
	
		
		
<a class="item" data-title="Installing Addons" href="../../cluster-administration/addons/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Kubernetes Architecture">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Nodes" href="../../../admin/node.1"></a>

		
	
		
		
<a class="item" data-title="Master-Node communication" href="../../architecture/master-node-communication/index.html"></a>

		
	
		
		
<a class="item" data-title="Concepts Underlying the Cloud Controller Manager" href="../../architecture/cloud-controller/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Extending Kubernetes">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Extending your Kubernetes Cluster" href="../../overview/extending/index.html"></a>

		
	
		
		
	<div class="item" data-title="Extending the Kubernetes API">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Extending the Kubernetes API with the aggregation layer" href="../apiserver-aggregation.1"></a>

		
	
		
		
<a class="item" data-title="Custom Resources" href="index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Compute, Storage, and Networking Extensions">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Network Plugins" href="../../../admin/network-plugins/index.html"></a>

		
	
		
		
<a class="item" data-title="Device Plugins" href="../../cluster-administration/device-plugins.1"></a>

		
	

		</div>
	</div>

		
	
		
		
<a class="item" data-title="Service Catalog" href="../../service-catalog/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Containers">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Images" href="../../containers/images/index.html"></a>

		
	
		
		
<a class="item" data-title="Container Environment Variables" href="../../containers/container-environment-variables/index.html"></a>

		
	
		
		
<a class="item" data-title="Container Lifecycle Hooks" href="../../containers/container-lifecycle-hooks/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Workloads">
		<div class="container">
		
		
	
	
		
		
	<div class="item" data-title="Pods">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Pod Overview" href="../../workloads/pods/pod-overview/index.html"></a>

		
	
		
		
<a class="item" data-title="Pods" href="../../../user-guide/pods/index.html"></a>

		
	
		
		
<a class="item" data-title="Pod Lifecycle" href="../../../user-guide/pod-states/index.html"></a>

		
	
		
		
<a class="item" data-title="Init Containers" href="../../abstractions/init-containers/index.html"></a>

		
	
		
		
<a class="item" data-title="Pod Preset" href="../../workloads/pods/podpreset/index.html"></a>

		
	
		
		
<a class="item" data-title="Disruptions" href="../../workloads/pods/disruptions/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Controllers">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="ReplicaSet" href="../../workloads/controllers/replicaset/index.html"></a>

		
	
		
		
<a class="item" data-title="ReplicationController" href="../../../user-guide/replication-controller/index.html"></a>

		
	
		
		
<a class="item" data-title="Deployments" href="../../workloads/controllers/deployment/index.html"></a>

		
	
		
		
<a class="item" data-title="StatefulSets" href="../../workloads/controllers/statefulset.md"></a>

		
	
		
		
<a class="item" data-title="DaemonSet" href="../../workloads/controllers/daemonset.1"></a>

		
	
		
		
<a class="item" data-title="Garbage Collection" href="../../workloads/controllers/garbage-collection/index.html"></a>

		
	
		
		
<a class="item" data-title="Jobs - Run to Completion" href="../../workloads/controllers/jobs-run-to-completion.1"></a>

		
	
		
		
<a class="item" data-title="CronJob" href="../../workloads/controllers/cron-jobs.1"></a>

		
	

		</div>
	</div>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Configuration">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Configuration Best Practices" href="../../configuration/overview/index.html"></a>

		
	
		
		
<a class="item" data-title="Managing Compute Resources for Containers" href="../../../user-guide/compute-resources/index.html"></a>

		
	
		
		
<a class="item" data-title="Assigning Pods to Nodes" href="../../../user-guide/node-selection/index.html"></a>

		
	
		
		
<a class="item" data-title="Taints and Tolerations" href="../../configuration/taint-and-toleration.1"></a>

		
	
		
		
<a class="item" data-title="Secrets" href="../../../user-guide/secrets.1"></a>

		
	
		
		
<a class="item" data-title="Organizing Cluster Access Using kubeconfig Files" href="../../configuration/organize-cluster-access-kubeconfig/index.html"></a>

		
	
		
		
<a class="item" data-title="Pod Priority and Preemption" href="../../configuration/pod-priority-preemption/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Services, Load Balancing, and Networking">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Services" href="../../../user-guide/services"></a>

		
	
		
		
<a class="item" data-title="DNS for Services and Pods" href="../../services-networking/dns-pod-service/index.html"></a>

		
	
		
		
<a class="item" data-title="Connecting Applications with Services" href="../../services-networking/connect-applications-service.1"></a>

		
	
		
		
<a class="item" data-title="Ingress" href="../../services-networking/ingress/index.html"></a>

		
	
		
		
<a class="item" data-title="Network Policies" href="../../services-networking/networkpolicies/index.html"></a>

		
	
		
		
<a class="item" data-title="Adding entries to Pod /etc/hosts with HostAliases" href="../../services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Storage">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Volumes" href="../../storage/volumes.1"></a>

		
	
		
		
<a class="item" data-title="Persistent Volumes" href="../../../user-guide/persistent-volumes/index.html"></a>

		
	
		
		
<a class="item" data-title="Storage Classes" href="../../storage/storage-classes.1"></a>

		
	
		
		
<a class="item" data-title="Dynamic Volume Provisioning" href="../../storage/dynamic-provisioning/index.html"></a>

		
	
		
		
<a class="item" data-title="Node-specific Volume Limits" href="../../storage/storage-limits/index.html"></a>

		
	

		</div>
	</div>

		
	
		
		
	<div class="item" data-title="Policies">
		<div class="container">
		
		
	
	
		
		
<a class="item" data-title="Resource Quotas" href="../../policy/resource-quotas/index.html"></a>

		
	
		
		
<a class="item" data-title="Pod Security Policies" href="../../../user-guide/pod-security-policy"></a>

		
	

		</div>
	</div>

		
	






     </div> 
    <button class="push-menu-close-button" onclick="kub.toggleToc()"></button>
</div> 

			<div id="docsContent">
				
<p><a href="../../../editdocs#docs/concepts/extend-kubernetes/api-extension/custom-resources.md" id="editPageButton">Edit This Page</a></p>

<h1>Custom Resources</h1>



<p>This page explains <em>custom resources</em>, which are extensions of the Kubernetes
API, including when to add a custom resource to your Kubernetes cluster and when
to use a standalone service. It describes the two methods for adding custom
resources and how to choose between them.</p>









<ul id="markdown-toc">










<li><a href="index.html#custom-resources">Custom resources</a></li>




<li><a href="index.html#adding-custom-resources">Adding custom resources</a></li>




<li><a href="index.html#customresourcedefinitions">CustomResourceDefinitions</a></li>




<li><a href="index.html#api-server-aggregation">API server aggregation</a></li>




<li><a href="index.html#preparing-to-install-a-custom-resource">Preparing to install a custom resource</a></li>




<li><a href="index.html#accessing-a-custom-resource">Accessing a custom resource</a></li>




















<li><a href="index.html#what-s-next">What's next</a></li>



</ul>


<h2 id="custom-resources">Custom resources</h2>

<p>A <em>resource</em> is an endpoint in the <a href="../../../reference/using-api/api-overview/index.html">Kubernetes API</a> that stores a collection of <a href="../../overview/working-with-objects/kubernetes-objects.1">API objects</a> of a certain kind. For example, the built-in <em>pods</em> resource contains a collection of Pod objects.</p>

<p>A <em>custom resource</em> is an extension of the Kubernetes API that is not necessarily available on every
Kubernetes cluster.
In other words, it represents a customization of a particular Kubernetes installation.</p>

<p>Custom resources can appear and disappear in a running cluster through dynamic registration,
and cluster admins can update custom resources independently of the cluster itself.
Once a custom resource is installed, users can create and access its objects with
<a href="../../../user-guide/kubectl-overview/index.html">kubectl</a>, just as they do for built-in resources like <em>pods</em>.</p>

<h3 id="custom-controllers">Custom controllers</h3>

<p>On their own, custom resources simply let you store and retrieve structured data.
It is only when combined with a <em>controller</em> that they become a true declarative API.
A <a href="../../overview/working-with-objects/kubernetes-objects.1#understanding-kubernetes-objects">declarative API</a>
allows you to <em>declare</em> or specify the desired state of your resource and tries
to match the actual state to this desired state.
Here, the controller interprets the structured data as a record of the user&rsquo;s
desired state, and continually takes action to achieve and maintain this state.</p>

<p>A <em>custom controller</em> is a controller that users can deploy and update on a running cluster, independently of the cluster&rsquo;s own lifecycle. Custom controllers can work with any kind of resource, but they are especially effective when combined with custom resources. The <a href="https://coreos.com/blog/introducing-operators.html" target="_blank">Operator</a> pattern is one example of such a combination. It allows developers to encode domain knowledge for specific applications into an extension of the Kubernetes API.</p>

<h3 id="should-i-add-a-custom-resource-to-my-kubernetes-cluster">Should I add a custom resource to my Kubernetes Cluster?</h3>

<p>When creating a new API, consider whether to <a href="../apiserver-aggregation/index.html">aggregate your API with the Kubernetes cluster APIs</a> or let your API stand alone.</p>

<table>
<thead>
<tr>
<th>Consider API aggregation if:</th>
<th>Prefer a stand-alone API if:</th>
</tr>
</thead>

<tbody>
<tr>
<td>Your API is <a href="index.html#declarative-apis">Declarative</a>.</td>
<td>Your API does not fit the <a href="index.html#declarative-apis">Declarative</a> model.</td>
</tr>

<tr>
<td>You want your new types to be readable and writable using <code>kubectl</code>.</td>
<td><code>kubectl</code> support is not required</td>
</tr>

<tr>
<td>You want to view your new types in a Kubernetes UI, such as dashboard, alongside built-in types.</td>
<td>Kubernetes UI support is not required.</td>
</tr>

<tr>
<td>You are developing a new API.</td>
<td>You already have a program that serves your API and works well.</td>
</tr>

<tr>
<td>You are willing to accept the format restriction that Kubernetes puts on REST resource paths, such as API Groups and Namespaces. (See the <a href="../../overview/kubernetes-api/index.html">API Overview</a>.)</td>
<td>You need to have specific REST paths to be compatible with an already defined REST API.</td>
</tr>

<tr>
<td>Your resources are naturally scoped to a cluster or to namespaces of a cluster.</td>
<td>Cluster or namespace scoped resources are a poor fit; you need control over the specifics of resource paths.</td>
</tr>

<tr>
<td>You want to reuse <a href="index.html#common-features">Kubernetes API support features</a>.</td>
<td>You don&rsquo;t need those features.</td>
</tr>
</tbody>
</table>

<h4 id="declarative-apis">Declarative APIs</h4>

<p>In a Declarative API, typically:</p>

<ul>
<li>Your API consists of a relatively small number of relatively small objects (resources).</li>
<li>The objects define configuration of applications or infrastructure.</li>
<li>The objects are updated relatively infrequently.</li>
<li>Humans often need to read and write the objects.</li>
<li>The main operations on the objects are CRUD-y (creating, reading, updating and deleting).</li>
<li>Transactions across objects are not required: the API represents a desired state, not an exact state.</li>
</ul>

<p>Imperative APIs are not declarative.
Signs that your API might not be declarative include:</p>

<ul>
<li>The client says &ldquo;do this&rdquo;, and then gets a synchronous response back when it is done.</li>
<li>The client says &ldquo;do this&rdquo;, and then gets an operation ID back, and has to check a separate Operation objects to determine completion of the request.</li>
<li>You talk about Remote Procedure Calls (RPCs).</li>
<li>Directly storing large amounts of data (e.g. &gt; a few kB per object, or &gt;1000s of objects).</li>
<li>High bandwidth access (10s of requests per second sustained) needed.</li>
<li>Store end-user data (such as images, PII, etc) or other large-scale data processed by applications.</li>
<li>The natural operations on the objects are not CRUD-y.</li>
<li>The API is not easily modeled as objects.</li>
<li>You chose to represent pending operations with an operation ID or operation object.</li>
</ul>

<h3 id="should-i-use-a-configmap-or-a-custom-resource">Should I use a configMap or a custom resource?</h3>

<p>Use a ConfigMap if any of the following apply:</p>

<ul>
<li>There is an existing, well-documented config file format, such as a <code>mysql.cnf</code> or <code>pom.xml</code>.</li>
<li>You want to put the entire config file into one key of a configMap.</li>
<li>The main use of the config file is for a program running in a Pod on your cluster to consume the file to configure itself.</li>
<li>Consumers of the file prefer to consume via file in a Pod or environment variable in a pod, rather than the Kubernetes API.</li>
<li>You want to perform rolling updates via Deployment, etc, when the file is updated.</li>
</ul>

<blockquote class="note">
  <div><strong>Note:</strong> Use a <a href="../../../user-guide/secrets.1">secret</a> for sensitive data, which is similar to a configMap but more secure.</div>
</blockquote>

<p>Use a custom resource (CRD or Aggregated API) if most of the following apply:</p>

<ul>
<li>You want to use Kubernetes client libraries and CLIs to create and update the new resource.</li>
<li>You want top-level support from kubectl (for example: <code>kubectl get my-object object-name</code>).</li>
<li>You want to build new automation that watches for updates on the new object, and then CRUD other objects, or vice versa.</li>
<li>You want to write automation that handles updates to the object.</li>
<li>You want to use Kubernetes API conventions like <code>.spec</code>, <code>.status</code>, and <code>.metadata</code>.</li>
<li>You want the object to be an abstraction over a collection of controlled resources, or a summarization of other resources.</li>
</ul>

<h2 id="adding-custom-resources">Adding custom resources</h2>

<p>Kubernetes provides two ways to add custom resources to your cluster:</p>

<ul>
<li>CRDs are simple and can be created without any programming.</li>
<li><a href="../apiserver-aggregation/index.html">API Aggregation</a> requires programming, but allows more control over API behaviors like how data is stored and conversion between API versions.</li>
</ul>

<p>Kubernetes provides these two options to meet the needs of different users, so that neither ease of use nor flexibility are compromised.</p>

<p>Aggregated APIs are subordinate APIServers that sit behind the primary API server, which acts as a proxy. This arrangement is called <a href="../apiserver-aggregation/index.html">API Aggregation</a> (AA). To users, it simply appears that the Kubernetes API is extended.</p>

<p>CRDs allow users to create new types of resources without adding another APIserver. You do not need to understand API Aggregation to use CRDs.</p>

<p>Regardless of how they are installed, the new resources are referred to as Custom Resources to distinguish them from built-in Kubernetes resources (like pods).</p>

<h2 id="customresourcedefinitions">CustomResourceDefinitions</h2>

<p>The <a href="../../../tasks/access-kubernetes-api/extend-api-custom-resource-definitions/index.html">CustomResourceDefinition</a> API resource allows you to define custom resources. Defining a CRD object creates a new custom resource with a name and schema that you specify. The Kubernetes API serves and handles the storage of your custom resource.</p>

<p>This frees you from writing your own API server to handle the custom resource,
but the generic nature of the implementation means you have less flexibility than with
<a href="index.html#api-server-aggregation">API server aggregation</a>.</p>

<p>Refer to the <a href="https://github.com/kubernetes/sample-controller" target="_blank">Custom Controller example, which uses Custom Resources</a>
for a demonstration of how to register a new custom resource, work with instances of your new resource type,
and setup a controller to handle events.</p>

<blockquote class="note">
  <div><strong>Note:</strong> CRD is the successor to the deprecated <em>ThirdPartyResource</em> (TPR) API, and is available as of Kubernetes 1.7.</div>
</blockquote>

<h2 id="api-server-aggregation">API server aggregation</h2>

<p>Usually, each resource in the Kubernetes API requires code that handles REST requests and manages persistent storage of objects. The main Kubernetes API server handles built-in resources like <em>pods</em> and <em>services</em>, and can also handle custom resources in a generic way through <a href="index.html#customresourcedefinitions">CRDs</a>.</p>

<p>The <a href="../apiserver-aggregation/index.html">aggregation layer</a> allows you to provide specialized
implementations for your custom resources by writing and deploying your own standalone API server.
The main API server delegates requests to you for the custom resources that you handle,
making them available to all of its clients.</p>

<h3 id="choosing-a-method-for-adding-custom-resources">Choosing a method for adding custom resources</h3>

<p>CRDs are easier to use. Aggregated APIs are more flexible. Choose the method that best meets your needs.</p>

<p>Typically, CRDs are a good fit if:</p>

<ul>
<li>You have a handful of fields</li>
<li>You are using the resource within your company, or as part of a small open-source project (as opposed to a commercial product)</li>
</ul>

<h4 id="comparing-ease-of-use">Comparing ease of use</h4>

<p>CRDs are easier to create than Aggregated APIs.</p>

<table>
<thead>
<tr>
<th>CRDs</th>
<th>Aggregated API</th>
</tr>
</thead>

<tbody>
<tr>
<td>Do not require programming. Users can choose any language for a CRD controller.</td>
<td>Requires programming in Go and building binary and image. Users can choose any language for a CRD controller.</td>
</tr>

<tr>
<td>No additional service to run; CRs are handled by API Server.</td>
<td>An additional service to create and that could fail.</td>
</tr>

<tr>
<td>No ongoing support once the CRD is created. Any bug fixes are picked up as part of normal Kubernetes Master upgrades.</td>
<td>May need to periodically pickup bug fixes from upstream and rebuild and update the Aggregated APIserver.</td>
</tr>

<tr>
<td>No need to handle multiple versions of your API. For example: when you control the client for this resource, you can upgrade it in sync with the API.</td>
<td>You need to handle multiple versions of your API, for example: when developing an extension to share with the world.</td>
</tr>
</tbody>
</table>

<h3 id="advanced-features-and-flexibility">Advanced features and flexibility</h3>

<p>Aggregated APIs offer more advanced API features and customization of other features, for example: the storage layer.</p>

<table>
<thead>
<tr>
<th>Feature</th>
<th>Description</th>
<th>CRDs</th>
<th>Aggregated API</th>
</tr>
</thead>

<tbody>
<tr>
<td>Validation</td>
<td>Help users prevent errors and allow you to evolve your API independently of your clients. These features are most useful when there are many clients who can&rsquo;t all update at the same time.</td>
<td>Yes.  Most validation can be specified in the CRD using <a href="../../../tasks/access-kubernetes-api/extend-api-custom-resource-definitions/index.html#validation">OpenAPI v3.0 validation</a>.  Any other validations supported by addition of a Validating Webhook.</td>
<td>Yes, arbitrary validation checks</td>
</tr>

<tr>
<td>Defaulting</td>
<td>See above</td>
<td>Yes, via a Mutating Webhook; Planned, via CRD OpenAPI schema.</td>
<td>Yes</td>
</tr>

<tr>
<td>Multi-versioning</td>
<td>Allows serving the same object through two API versions. Can help ease API changes like renaming fields. Less important if you control your client versions.</td>
<td>No, but planned</td>
<td>Yes</td>
</tr>

<tr>
<td>Custom Storage</td>
<td>If you need storage with a different performance mode (for example, time-series database instead of key-value store) or isolation for security (for example, encryption secrets or different</td>
<td>No</td>
<td>Yes</td>
</tr>

<tr>
<td>Custom Business Logic</td>
<td>Perform arbitrary checks or actions when creating, reading, updating or deleting an object</td>
<td>Yes, using Webhooks.</td>
<td>Yes</td>
</tr>

<tr>
<td>Scale Subresource</td>
<td>Allows systems like HorizontalPodAutoscaler and PodDisruptionBudget interact with your new resource</td>
<td><a href="https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/#scale-subresource" target="_blank">Yes</a></td>
<td>Yes</td>
</tr>

<tr>
<td>Status Subresource</td>
<td><ul><li>Finer-grained access control: user writes spec section, controller writes status section.</li><li>Allows incrementing object Generation on custom resource data mutation (requires separate spec and status sections in the resource)</li></ul></td>
<td><a href="https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/#status-subresource" target="_blank">Yes</a></td>
<td>Yes</td>
</tr>

<tr>
<td>Other Subresources</td>
<td>Add operations other than CRUD, such as &ldquo;logs&rdquo; or &ldquo;exec&rdquo;.</td>
<td>No</td>
<td>Yes</td>
</tr>

<tr>
<td>strategic-merge-patch</td>
<td>The new endpoints support PATCH with <code>Content-Type: application/strategic-merge-patch+json</code>. Useful for updating objects that may be modified both locally, and by the server. For more information, see <a href="../../../tasks/run-application/update-api-object-kubectl-patch/index.html">&ldquo;Update API Objects in Place Using kubectl patch&rdquo;</a></td>
<td>No, but similar functionality planned</td>
<td>Yes</td>
</tr>

<tr>
<td>Protocol Buffers</td>
<td>The new resource supports clients that want to use Protocol Buffers</td>
<td>No</td>
<td>Yes</td>
</tr>

<tr>
<td>OpenAPI Schema</td>
<td>Is there an OpenAPI (swagger) schema for the types that can be dynamically fetched from the server? Is the user protected from misspelling field names by ensuring only allowed fields are set? Are types enforced (in other words, don&rsquo;t put an <code>int</code> in a <code>string</code> field?)</td>
<td>No, but planned</td>
<td>Yes</td>
</tr>
</tbody>
</table>

<h4 id="common-features">Common Features</h4>

<p>When you create a custom resource, either via a CRDs or an AA, you get many features for your API, compared to implementing it outside the Kubernetes platform:</p>

<table>
<thead>
<tr>
<th>Feature</th>
<th>What it does</th>
</tr>
</thead>

<tbody>
<tr>
<td>CRUD</td>
<td>The new endpoints support CRUD basic operations via HTTP and <code>kubectl</code></td>
</tr>

<tr>
<td>Watch</td>
<td>The new endpoints support Kubernetes Watch operations via HTTP</td>
</tr>

<tr>
<td>Discovery</td>
<td>Clients like kubectl and dashboard automatically offer list, display, and field edit operations on your resources</td>
</tr>

<tr>
<td>json-patch</td>
<td>The new endpoints support PATCH with <code>Content-Type: application/json-patch+json</code></td>
</tr>

<tr>
<td>merge-patch</td>
<td>The new endpoints support PATCH with <code>Content-Type: application/merge-patch+json</code></td>
</tr>

<tr>
<td>HTTPS</td>
<td>The new endpoints uses HTTPS</td>
</tr>

<tr>
<td>Built-in Authentication</td>
<td>Access to the extension uses the core apiserver (aggregation layer) for authentication</td>
</tr>

<tr>
<td>Built-in Authorization</td>
<td>Access to the extension can reuse the authorization used by the core apiserver (e.g. RBAC)</td>
</tr>

<tr>
<td>Finalizers</td>
<td>Block deletion of extension resources until external cleanup happens.</td>
</tr>

<tr>
<td>Admission Webhooks</td>
<td>Set default values and validate extension resources during any create/update/delete operation.</td>
</tr>

<tr>
<td>UI/CLI Display</td>
<td>Kubectl, dashboard can display extension resources.</td>
</tr>

<tr>
<td>Unset vs Empty</td>
<td>Clients can distinguish unset fields from zero-valued fields.</td>
</tr>

<tr>
<td>Client Libraries Generation</td>
<td>Kubernetes provides generic client libraries, as well as tools to generate type-specific client libraries.</td>
</tr>

<tr>
<td>Labels and annotations</td>
<td>Common metadata across objects that tools know how to edit for core and custom resources.</td>
</tr>
</tbody>
</table>

<h2 id="preparing-to-install-a-custom-resource">Preparing to install a custom resource</h2>

<p>There are several points to be aware of before adding a custom resource to your cluster.</p>

<h3 id="third-party-code-and-new-points-of-failure">Third party code and new points of failure</h3>

<p>While creating a CRD does not automatically add any new points of failure (for example, by causing third party code to run on your API server), packages (for example, Charts) or other installation bundles often include CRDs as well as a Deployment of third-party code that implements the business logic for a new custom resource.</p>

<p>Installing an Aggregated APIserver always involves running a new Deployment.</p>

<h3 id="storage">Storage</h3>

<p>Custom resources consume storage space in the same way that ConfigMaps do. Creating too many custom resources may overload your API server&rsquo;s storage space.</p>

<p>Aggregated API servers may use the same storage as the main API server, in which case the same warning applies.</p>

<h3 id="authentication-authorization-and-auditing">Authentication, authorization, and auditing</h3>

<p>CRDs always use the same authentication, authorization, and audit logging as the built-in resources of your API Server.</p>

<p>If you use RBAC for authorization, most RBAC roles will not grant access to the new resources (except the cluster-admin role or any role created with wildcard rules). You&rsquo;ll need to explicitly grant access to the new resources. CRDs and Aggregated APIs often come bundled with new role definitions for the types they add.</p>

<p>Aggregated API servers may or may not use the same authentication, authorization, and auditing as the primary API server.</p>

<h2 id="accessing-a-custom-resource">Accessing a custom resource</h2>

<p>Kubernetes <a href="../../../reference/using-api/client-libraries/index.html">client libraries</a> can be used to access custom resources. Not all client libraries support custom resources. The go and python client libraries do.</p>

<p>When you add a custom resource, you can access it using:</p>

<ul>
<li>kubectl</li>
<li>The kubernetes dynamic client.</li>
<li>A REST client that you write.</li>
<li>A client generated using <a href="https://github.com/kubernetes/code-generator" target="_blank">Kubernetes client generation tools</a> (generating one is an advanced undertaking, but some projects may provide a client along with the CRD or AA).</li>
</ul>












<h2 id="what-s-next">What&#39;s next</h2>
<ul>
<li>Learn how to <a href="../apiserver-aggregation/index.html">Extend the Kubernetes API with the aggregation layer</a>.</li>
<li>Learn how to <a href="../../../tasks/access-kubernetes-api/extend-api-custom-resource-definitions/index.html">Extend the Kubernetes API with CustomResourceDefinition</a>.</li>
<li>Learn how to <a href="../../../tasks/access-kubernetes-api/migrate-third-party-resource/index.html">Migrate a ThirdPartyResource to CustomResourceDefinition</a>.</li>
</ul>






				<div class="issue-button-container">
					<p><a href="index.html"><img src="https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/concepts/extend-kubernetes/api-extension/custom-resources.md?pixel" alt="Analytics" /></a></p>
					
					
					<script type="text/javascript">
					PDRTJS_settings_8345992 = {
					"id" : "8345992",
					"unique_id" : "\/docs\/concepts\/extend-kubernetes\/api-extension\/custom-resources\/",
					"title" : "Custom Resources",
					"permalink" : "https:\/\/kubernetes.io\/docs\/concepts\/extend-kubernetes\/api-extension\/custom-resources\/"
					};
					(function(d,c,j){if(!document.getElementById(j)){var pd=d.createElement(c),s;pd.id=j;pd.src=('https:'==document.location.protocol)?'https://polldaddy.com/js/rating/rating.js':'http://i0.poll.fm/js/rating/rating.js';s=document.getElementsByTagName(c)[0];s.parentNode.insertBefore(pd,s);}}(document,'script','pd-rating-js'));
					</script>
					<a href="index.html" onclick="window.open('https://github.com/kubernetes/website/issues/new?title=Issue%20with%20' +
					'k8s.io'+window.location.pathname)" class="button issue">Create an Issue</a>
					
					
					
					<a href="../../../editdocs#docs/concepts/extend-kubernetes/api-extension/custom-resources.md" class="button issue">Edit this Page</a>
					
				</div>
			</div>
		</section>
		<footer>
    <main class="light-text">
        <nav>
            
            
            
            <a href="../../../home.1">Documentation</a>
            
            <a href="../../../../blog/index.html">Blog</a>
            
            <a href="../../../../partners/index.html">Partners</a>
            
            <a href="../../../../community/index.html">Community</a>
            
            <a href="../../../../case-studies/index.html">Case Studies</a>
            
        </nav>
        <div class="social">
            <div>
                <a href="https://twitter.com/kubernetesio" class="twitter"><span>twitter</span></a>
                <a href="https://github.com/kubernetes/kubernetes" class="github"><span>Github</span></a>
                <a href="http://slack.k8s.io/" class="slack"><span>Slack</span></a>
            </div>
            <div>
                <a href="http://stackoverflow.com/questions/tagged/kubernetes" class="stack-overflow"><span>Stack Overflow</span></a>
                <a href="https://discuss.kubernetes.io" class="mailing-list"><span>Forum</span></a>
                <a href="https://calendar.google.com/calendar/embed?src=nt2tcnbtbied3l6gi2h29slvc0%40group.calendar.google.com" class="calendar"><span>Events Calendar</span></a>
            </div>
            <div>
                <a href="../../../getting-started-guides/index.html" class="button">Get Kubernetes</a>
                <a href="https://git.k8s.io/community/contributors/guide" class="button">Contribute</a>
            </div>
        </div>
        <div id="miceType" class="center">
            &copy; 2018 The Kubernetes Authors | Documentation Distributed under <a href="https://git.k8s.io/website/LICENSE" class="light-text">CC BY 4.0</a>
        </div>
        <div id="miceType" class="center">
            Copyright &copy; 2018 The Linux Foundation&reg;. All rights reserved. The Linux Foundation has registered trademarks and uses trademarks. For a list of trademarks of The Linux Foundation, please see our <a href="https://www.linuxfoundation.org/trademark-usage" class="light-text">Trademark Usage page</a>
        </div>
    </main>
</footer>

		<button class="flyout-button" onclick="kub.toggleToc()"></button>

<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-36037335-10', 'auto');
ga('send', 'pageview');


(function () {
    window.addEventListener('DOMContentLoaded', init)

        
        function init() {
            window.removeEventListener('DOMContentLoaded', init)
                hideNav()
        }

    function hideNav(toc){
        if (!toc) toc = document.querySelector('#docsToc')
        if (!toc) return
            var container = toc.querySelector('.container')

                
                if (container) {
                    if (container.childElementCount === 0 || toc.querySelectorAll('a.item').length === 1) {
                        toc.style.display = 'none'
                            document.getElementById('docsContent').style.width = '100%'
                    }
                } else {
                    requestAnimationFrame(function () {
                        hideNav(toc)
                    })
                }
    }
})();
</script>



	</body>
</html>